package org.particlethink.auth;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@EnableWebSecurity
@Configuration
public class SpringConfig {

	/**
	 * 安全元数据源
	 */
	@Autowired
	private FilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource;

	/**
	 * 访问决策管理器
	 */
	@Autowired
	private AccessDecisionManager accessDecisionManager;

	/**
	 * 用户信息加载器
	 */
	@Autowired
    @Qualifier("UserDetailsService")
	private UserDetailsService userDetailsService;

	/**
	 * 登录成功处理器
	 */
//	@Bean
	private LogoutSuccessHandler logoutSuccessHandler;

	/**
	 * 权限被拒绝时
	 */
	@Autowired
	private AccessDeniedHandler accessDeniedHandler;

	/**
	 * 匿名用户访问无权限资源时
	 */
	@Autowired
	private AuthenticationEntryPoint authenticationEntryPoint;

	/**
	 * 用户登录配置
	 */
	@Autowired
	private CustomizedUserProperties customizedUserProperties;

	/**
	 * 重写spring security的登录时获取用户名和密码的策略
	 */
//	private IObtainUsernameAndPasswordHandler obtainUsernameAndPassword;

	/**
	 * 用户登录失败的处理器
	 */
	@Autowired
	private AuthenticationFailureHandler authenticationFailureHandler;

	/**
	 * 用户登录成功的处理器
	 */
	@Autowired
	private AuthenticationSuccessHandler authenticationSuccessHandler;

	@Autowired
	private UserTokenWithRedisHandlerAdapter userTokenWithRedisHandlerAdapter;

//	@Autowired
//	private AuthenticationManager authenticationManager;

	private boolean authenticationManagerInitialized;

	@Autowired
	private AuthenticationConfiguration configuration;

	private CustomizedUsernamePasswordAuthenticationFilter customizedUsernamePasswordAuthenticationFilter() throws Exception {
		CustomizedUsernamePasswordAuthenticationFilter filter = new CustomizedUsernamePasswordAuthenticationFilter();
		//自定义处理获取用户名密码的处理器
//		filter.setiObtainUsernameAndPasswordHandler(obtainUsernameAndPassword);
		//身份认证处理器
		filter.setAuthenticationManager(configuration.getAuthenticationManager());
		//登陆失败
		filter.setAuthenticationFailureHandler(authenticationFailureHandler);
		//登陆成功
		filter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
		//设置登陆路径
		filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(customizedUserProperties.getSignIn().getLoginUrl(), HttpMethod.POST.name()));
		//禁用session
		filter.setAllowSessionCreation(false);
		filter.afterPropertiesSet();
		return filter;
	}


    @Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        UrlBasedCorsConfigurationSource corsConfig = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfig.registerCorsConfiguration("/**", corsConfiguration);

        http.cors().configurationSource(corsConfig)
                .and()
				.csrf()
				.disable()
				.formLogin()
				.disable();
		http.authorizeRequests()
				.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
					@Override
					public <O extends FilterSecurityInterceptor> O postProcess(O o) {
						//安全数据源
						o.setSecurityMetadataSource(filterInvocationSecurityMetadataSource);
						//访问决策管理器
						o.setAccessDecisionManager(accessDecisionManager);
						o.afterPropertiesSet();
						return o;
					}
				})
				.and()
				.userDetailsService(userDetailsService)
				.logout()
				.permitAll()
//				.logoutUrl(customizedUserProperties.getSignIn().getLogoutUrl())
//				.logoutSuccessHandler(logoutSuccessHandler)
				.and()
				.exceptionHandling()
				.accessDeniedHandler(accessDeniedHandler)
				.authenticationEntryPoint(authenticationEntryPoint);

		//替换原本的用户登录逻辑
		http.addFilterAt(customizedUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

		TokenFilter filter = new TokenFilter();
		filter.setHandlerAdapter(userTokenWithRedisHandlerAdapter);
		/**
		 * 放在默认的加载用户过滤器后
		 */
		http.addFilterAfter(filter, AnonymousAuthenticationFilter.class);

		return http.build();
	}
}
